from collections import OrderedDict
import os
from datetime import datetime

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from django.conf import settings
from apps import redis_client
from .models import Scripts
from .serializer import *
from util.auth import OWNTokenAuthentication
from util.page import MyPageNumberPagination
from util.exception import ValidationError


class ScriptsView(GenericViewSet):
    authentication_classes = [OWNTokenAuthentication]

    @action(detail=False, methods=["POST", ], url_path="create")
    def script_create(self, requests, *args, **kwargs):
        data = {}
        data["name"] = requests.data.get("name")
        serializer = ScriptsSeriallizer(data=data)
        if serializer.is_valid():
            serializer.create(serializer.validated_data)
            return Response({"code": 200, "msg": "添加脚本库成功"})
        raise ValidationError(20001)

    @action(detail=False, methods=["POST", ], url_path="update")
    def script_update(self, requests, *args, **kwargs):
        data = {}
        data["id"] = requests.data.get("id")
        serializer = ScriptsUpdateSeriallizer(data=data)
        if serializer.is_valid():
            instance = Scripts.objects.filter(id=serializer.validated_data["id"]).first()
            serializer.update(instance, serializer.validated_data)
            return Response({"code": 200, "msg": "修改脚本库成功"})
        raise ValidationError(20001)

    @action(detail=False, methods=["GET", ], url_path="list")
    def script_list(self, requests, *args, **kwargs):
        name = requests.GET.get("name")
        if name:
            scripts = Scripts.objects.filter(is_delete=False, name__icontains=name).all()
            if not scripts:
                scripts = Scripts.objects.filter(is_delete=False).all()
        else:
            scripts = Scripts.objects.filter(is_delete=False).all()
        page = MyPageNumberPagination()
        scripts = page.paginate_queryset(queryset=scripts, request=requests, view=self)
        scipt_re = ScriptsListSeriallizer(instance=scripts, many=True)
        return Response(self.__get_paginated_response(page, requests, scipt_re.data))

    @action(detail=False, methods=["GET", ], url_path="no_page_list")
    def script_on_page_list(self, requests, *args, **kwargs):
        scripts = Scripts.objects.filter(is_delete=False).all()
        data = []
        for script in scripts:
            data.append({
                "value": script.id,
                "label": script.name
            })
        return Response({
            "code": 200,
            "result": data
        })


    def __get_paginated_response(self, page, request, datas):
        a = OrderedDict([
            ('current', int(page.get_page_number(request, page))),
            ('total', int(page.page.paginator.count)),
            ('pageSize', int(page.get_page_size(request))),
            ('data', datas)
        ])
        return a

    @action(detail=False, methods=["GET", ], url_path="files_list")
    def files_list(self, requests, *args, **kwargs):
        script_id = requests.GET.get("id")
        script = Scripts.objects.filter(id=script_id).first()
        if not script:
            raise ValidationError(50003)
        file_path = script.file_path
        if not os.path.isdir(file_path):
            os.mkdir(file_path)
        files = os.listdir(file_path)
        return Response({"code": 200, "data": files})

    @action(detail=False, methods=["POST", ], url_path="files_upload")
    def files_write(self, requests, *args, **kwargs):
        script_id = requests.GET.get("id")
        script = Scripts.objects.filter(id=script_id).first()
        if not script:
            raise ValidationError(50003)
        file_path = script.file_path
        if not os.path.isdir(file_path):
            os.mkdir(file_path)
        myFile = requests.FILES.get("file")
        if not myFile:
            raise ValidationError(50002)
        name = myFile.name
        destination = open(os.path.join(file_path, name), "wb+")
        for chunk in myFile.chunks():
            destination.write(chunk)
        destination.close()
        return Response({
            "code": 200,
            "msg": "上传成功"
        })

    @action(detail=False, methods=["POST", ], url_path="files_delete")
    def files_delete(self, requests, *args, **kwargs):
        data = {}
        data["id"] = requests.data.get("id")
        data["files"] = requests.data.get("files")
        serializers = ScriptsFileDeleteSeriallizer(data=data)
        if serializers.is_valid():
            script_id = serializers.validated_data.get("id")
            files = serializers.validated_data.get("files", [])
            script = Scripts.objects.filter(id=script_id).first()
            if not script:
                raise ValidationError(50003)
            file_path = script.file_path
            if not os.path.isdir(file_path):
                os.mkdir(file_path)
            for file in files:
                delete_path = "".join([file_path, "/", file])
                if os.path.exists(delete_path):
                    os.remove(delete_path)
            return Response({
                "code": 200,
                "msg": "删除成功"
            })
        else:
            raise ValidationError(20001)

    @action(detail=False, methods=["GET", ], url_path="files_show")
    def files_show(self, requests, *args, **kwargs):
        data = {}
        data["id"] = requests.GET.get("id")
        data["file_name"] = requests.GET.get("file_name")
        serializers = ScriptsFileShowSeriallizer(data=data)
        if serializers.is_valid():
            script_id = serializers.validated_data["id"]
            file_name = serializers.validated_data["file_name"]
            instance = Scripts.objects.filter(id=script_id, is_delete=False).first()
            if not instance:
                raise ValidationError(50003)
            file_path = instance.file_path
            file_path = "".join([file_path, "/", file_name])
            if not os.path.isfile(file_path):
                raise ValidationError(50004)
            content = self.__show_file(file_path)
            return Response({
                "code": 200,
                "result": content
            })
        else:
            raise ValidationError(20001)

    def __show_file(self, file_path):
        content = ""
        try:
            f = open(file_path, "r", encoding="utf-8")
            while True:
                re = f.readline()
                content += re
                if not re:
                    break
        except Exception as e:
            raise ValidationError(60001)
        f.close()
        return content


    @action(detail=False, methods=["POST", ], url_path="files_content")
    def files_content(self, requests, *args, **kwargs):
        data = {}
        data["id"] = requests.data.get("id")
        data["file_name"] = requests.data.get("file_name")
        data["content"] = requests.data.get("content")
        serializers = ScriptsFileContentSeriallizer(data=data)
        if serializers.is_valid():
            script_id = serializers.validated_data["id"]
            file_name = serializers.validated_data["file_name"]
            content = serializers.validated_data["content"]
            instance = Scripts.objects.filter(id=script_id, is_delete=False).first()
            if not instance:
                raise ValidationError(50003)
            file_path = instance.file_path
            file_path = "".join([file_path, "/", file_name])
            self.__write_content(content, file_path)
            return Response({
                "code": 200,
                "msg": "修改成功"
            })
        else:
            raise ValidationError(20001)

    def __write_content(self, content, file_path):
        try:
            f = open(file_path, "w", encoding="utf-8")
            f.write(content)
            f.close()
        except Exception as e:
            raise ValidationError(60002)